package com.sencorsta.ids.core.tcp.socket.client;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.sencorsta.ids.core.configure.SysConfig;
import com.sencorsta.ids.core.log.Out;

import com.sencorsta.ids.core.tcp.socket.protocol.RpcMessage;
import com.sencorsta.utils.string.StringUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.ThreadPerTaskExecutor;

public class RpcClientBootstrap {
    // 存放NIO客户端实例对象
    private static Map<String, RpcClientBootstrap> clientMap = new HashMap<String, RpcClientBootstrap>();

    private String serverIp;
    private int serverPort;
    private Bootstrap bootstrap;
    private EventLoopGroup group;
    //private ChannelFuture channelFuture;
    //protected Channel nettyChannel;

//    private static final int CHILDGROUP_SIZE = SysConfig.getInstance().getInt("netty.server.childgroup.size", 4);
    //private static final EventLoopGroup m_loop = new NioEventLoopGroup();
//	public Channel getChannel() {
//		return channelFuture.channel();
//	}

//    public RpcClientBootstrap(ChannelInitializer<SocketChannel> factory) {
//        this(factory);
//    }

    public RpcClientBootstrap(String name,ChannelInitializer<SocketChannel> factory) {
        group = new NioEventLoopGroup(0,new ThreadPerTaskExecutor(new DefaultThreadFactory(name+"Send")));
        bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.option(ChannelOption.TCP_NODELAY, true);
        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
        bootstrap.handler(factory);
        bootstrap.group(group);

        // channelFuture = bootstrap.connect(serverIp, serverPort).sync();
    }

    public Channel connect(String host, int port) {
        try {
            this.serverIp = host;
            this.serverPort = port;
            ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
            future.awaitUninterruptibly(3, TimeUnit.SECONDS);
            if (!future.isSuccess()) {
                if (future.cause() != null) {
                    Out.trace("连接服务器出错:",future.cause().getMessage());
                }
                return null;
            }
            //nettyChannel = future.channel();
            return future.channel();
        } catch (Exception e) {
            Out.error("连接服务器出错", "host:", host, " port:", port + " -> " + e.getMessage());
            //e.printStackTrace();
            return null;
        }
    }

//	/**
//	 * @description ip和port唯一确定对同一NIO Server同ip、port只创建一次
//	 * @param ip
//	 * @param port
//	 * @return nio客户端对象
//	 * @throws InterruptedException
//	 */
//	public static OpenClientBootstrap getInstance(String key) throws InterruptedException {
//		OpenClientBootstrap niosocket = null;
//		if (clientMap.containsKey(key)) {
//			niosocket = clientMap.get(key);
//		} else {
//			niosocket = new OpenClientBootstrap();
//			clientMap.put(key, niosocket);
//		}
//		return niosocket;
//	}

//    public void write(Object obj) {
//        if (!channelFuture.channel().isOpen() || !channelFuture.channel().isWritable() || obj == null) {
//            return;
//        }
//        channelFuture.channel().writeAndFlush(obj);
//    }

    public void close(Channel channel) throws InterruptedException {
        Out.trace("开始关闭链接");
        channel.closeFuture().sync();
        group.shutdownGracefully();
        clientMap.remove(serverIp + ":" + serverPort);
        Out.trace("关闭链接");
    }

}
